package edu.cmu.cs.webapp.ioms.views;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;

import edu.cmu.cs.webapp.ioms.IOMSActivator;
import edu.cmu.cs.webapp.ioms.dao.DataAccessException;
import edu.cmu.cs.webapp.ioms.dao.impl.IngredientDAOImpl;
import edu.cmu.cs.webapp.ioms.logging.Alerts;
import edu.cmu.cs.webapp.ioms.models.Ingredient;
import edu.cmu.cs.webapp.ioms.ui.providers.order.InventoryTableViewerContentProvider;
import edu.cmu.cs.webapp.ioms.ui.providers.order.InventoryTableViewerLabelProvider;
import edu.cmu.cs.webapp.ioms.utils.IOMSConstants;
import edu.cmu.cs.webapp.ioms.utils.IOMSUtils;
import edu.cmu.cs.webapp.ioms.utils.SWTUtils;

/**
 * 
 * @author Christian
 * 
 */
public class InventoryView extends ViewPart implements ISelectionProvider {
	public static final String ID_VIEW = "edu.cmu.cs.webapp.ioms.views.inventory";

	private TableViewer viewer;
	private InventoryFilter viewerFilter;

	private Table table;
	private Combo searchChoice;
	private Text searchText;
	InventoryTableViewerLabelProvider labelProvider;
	private Ingredient[] ings;

	private Spinner inventorySaftyLevel;

	public InventoryView() {
		viewerFilter = new InventoryFilter();
		labelProvider = new InventoryTableViewerLabelProvider(
				0.01 * IOMSActivator.getDefault().getPreferenceStore().getInt(
						IOMSConstants.SATEFY_PREF_KEY));
	}

	@Override
	public void init(IViewSite site) throws PartInitException {
		super.init(site);
		site.setSelectionProvider(this);
	}

	@Override
	public void createPartControl(Composite parent) {
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 1;
		gridLayout.marginHeight = 2;
		gridLayout.marginWidth = 2;

		parent.setLayout(gridLayout);

		Composite composite = new Composite(parent, SWT.NONE);
		GridData gridCompositeData = new GridData();
		gridCompositeData.verticalAlignment = GridData.BEGINNING;
		gridCompositeData.horizontalAlignment = GridData.FILL;
		gridCompositeData.grabExcessHorizontalSpace = true;
		gridCompositeData.horizontalSpan = 1;

		composite.setLayoutData(gridCompositeData);

		GridLayout gridCompositeGroupLayout = new GridLayout();
		gridCompositeGroupLayout.numColumns = 6;
		composite.setLayout(gridCompositeGroupLayout);

		Label searchLabel = new Label(composite, SWT.NONE);
		searchLabel.setText("Filter By:"); //$NON-NLS-1$

		searchChoice = SWTUtils.createCombo(composite, new String[] {
				"Ingredient ID", "Ingredient Name", "Demand", "Stock",
				"Safety", "Unit Price" }, 1);
		searchChoice.select(0);

		searchText = new Text(composite, SWT.BORDER);
		GridData txtGridData = new GridData(GridData.FILL_HORIZONTAL);
		txtGridData.horizontalAlignment = SWT.FILL;
		txtGridData.grabExcessHorizontalSpace = true;
		searchText.setLayoutData(txtGridData);
		searchText.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent event) {
				Text text = (Text) event.widget;
				viewerFilter.setText(text.getText());
				viewer.refresh();
			}
		});

		Label satftyLevel = new Label(composite, SWT.NONE);
		satftyLevel.setText("Safty Level(Percentage):"); //$NON-NLS-1$
		GridData sfGD = new GridData();
		sfGD.horizontalAlignment = SWT.END;
		satftyLevel.setLayoutData(sfGD);

		inventorySaftyLevel = new Spinner(composite, SWT.BORDER | SWT.WRAP);
		GridData scaleGD = new GridData();
		scaleGD.horizontalAlignment = SWT.FILL;
		inventorySaftyLevel.setLayoutData(scaleGD);
		inventorySaftyLevel.setDigits(2);
		inventorySaftyLevel.setMinimum(0);
		inventorySaftyLevel.setMaximum(100);
		inventorySaftyLevel.setSelection(IOMSActivator.getDefault()
				.getPreferenceStore().getInt(IOMSConstants.SATEFY_PREF_KEY));

		Button applyBtn = SWTUtils.createPushButton(composite, "Apply");
		applyBtn.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				labelProvider.setSafetyLevel(0.01 * inventorySaftyLevel
						.getSelection());

				// safe to pref store
				IOMSActivator.getDefault().getPreferenceStore().setValue(
						IOMSConstants.SATEFY_PREF_KEY,
						inventorySaftyLevel.getSelection());
				refreshInventoryView();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {

			}
		});

		createTableViewer(parent);
	}

	public void createTableViewer(Composite parent) {

		/*
		 * Create table
		 */
		GridData gridData = new GridData();
		gridData.horizontalSpan = 1;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		gridData.verticalAlignment = GridData.FILL;

		table = new Table(parent, SWT.FULL_SELECTION | SWT.BORDER
				| SWT.H_SCROLL | SWT.V_SCROLL);
		table.setLayoutData(gridData);

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		// id
		TableColumn idColumn = new TableColumn(table, SWT.NONE);
		idColumn.setText("#"); //$NON-NLS-1$
		idColumn.setWidth(60);
		idColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new InventorySorter(
						InventoryTableViewerLabelProvider.ID,
						sortDirection == SWT.DOWN));
			}
		});

		// ing name
		TableColumn nameColumn = new TableColumn(table, SWT.NONE);
		nameColumn.setText("Ingredient Name"); //$NON-NLS-1$
		nameColumn.setWidth(170);
		nameColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new InventorySorter(
						InventoryTableViewerLabelProvider.NAME,
						sortDirection == SWT.DOWN));
			}
		});

		// demand
		TableColumn demandColumn = new TableColumn(table, SWT.NONE);
		demandColumn.setText("Demand"); //$NON-NLS-1$
		demandColumn.setWidth(120);
		demandColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new InventorySorter(
						InventoryTableViewerLabelProvider.DEMAND,
						sortDirection == SWT.DOWN));
			}
		});

		// stock level
		TableColumn stockColumn = new TableColumn(table, SWT.NONE);
		stockColumn.setText("Stock Level"); //$NON-NLS-1$
		stockColumn.setWidth(120);
		stockColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new InventorySorter(
						InventoryTableViewerLabelProvider.STOCK,
						sortDirection == SWT.DOWN));
			}
		});

		// safety Level
		TableColumn saftyColumn = new TableColumn(table, SWT.NONE);
		saftyColumn.setText("Safety Level"); //$NON-NLS-1$
		saftyColumn.setWidth(120);
		saftyColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new InventorySorter(
						InventoryTableViewerLabelProvider.SAFETY,
						sortDirection == SWT.DOWN));
			}
		});

		// unit price
		TableColumn unitPriceColumn = new TableColumn(table, SWT.NONE);
		unitPriceColumn.setText("Unit Price"); //$NON-NLS-1$
		unitPriceColumn.setWidth(100);
		unitPriceColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new InventorySorter(
						InventoryTableViewerLabelProvider.PRICE,
						sortDirection == SWT.DOWN));
			}
		});

		// Last update
		TableColumn updateByColumn = new TableColumn(table, SWT.NONE);
		updateByColumn.setText("Last Update"); //$NON-NLS-1$
		updateByColumn.setWidth(100);
		updateByColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new InventorySorter(
						InventoryTableViewerLabelProvider.LAST_UPDATE,
						sortDirection == SWT.DOWN));
			}
		});

		/*
		 * Create viewer
		 */
		viewer = new TableViewer(table);

		viewer.setUseHashlookup(true);
		viewer.addFilter(viewerFilter);

		viewer.setLabelProvider(labelProvider);
		viewer.setContentProvider(new InventoryTableViewerContentProvider());

		// tableViewer.setComparator(new
		// TableViewerComparator(this.tableViewer));

		refreshInventoryView();
	}

	public void refreshInventoryView() {
		UIJob refreshJob = new RefreshJob("Refresh");
		refreshJob.setUser(true);
		refreshJob.schedule();
	}

	@Override
	public void setFocus() {

	}

	private final class InventoryFilter extends ViewerFilter {
		private String text;

		public void setText(final String s) {
			this.text = s;
		}

		public boolean select(final Viewer viewer, final Object parentElement,
				final Object element) {
			boolean result = true;
			if (text != null && text.length() > 0) {
				String txt = labelProvider.getColumnText(element, searchChoice
						.getSelectionIndex());
				result = txt.toLowerCase().indexOf(text.toLowerCase()) != -1;
			}
			return result;
		}

		public boolean isFilterProperty(final Object element, final String prop) {
			return true;
		}
	}

	@Override
	public void addSelectionChangedListener(ISelectionChangedListener listener) {
		this.viewer.addSelectionChangedListener(listener);
	}

	@Override
	public ISelection getSelection() {
		return this.viewer.getSelection();
	}

	@Override
	public void removeSelectionChangedListener(
			ISelectionChangedListener listener) {
		this.viewer.removeSelectionChangedListener(listener);

	}

	@Override
	public void setSelection(ISelection selection) {
		this.viewer.setSelection(selection);
	}

	private class RefreshJob extends UIJob {

		public RefreshJob(String name) {
			super(name);
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			monitor.beginTask("Refreshing Orders List...",
					IProgressMonitor.UNKNOWN);
			try {

				ings = new IngredientDAOImpl().getAllIngr().toArray(
						new Ingredient[0]);

				for (Ingredient ing : ings) {
					ing.setDemand(new IngredientDAOImpl().findDemandLevel(ing
							.getIng_id()));
				}

			} catch (DataAccessException e) {
				Alerts.getInstance().detailError("Data Access Error",
						e.getLocalizedMessage(), e);
				return Status.CANCEL_STATUS;
			}

			if (ings != null) {
				viewer.setInput(ings);
			}

			monitor.done();

			return Status.OK_STATUS;
		}
	}

	/**
	 * 
	 * @param site
	 * @return
	 */
	public static InventoryView getInventoryView(IViewSite site) {
		IViewPart view = site.getPage().findView(InventoryView.ID_VIEW);
		if (view instanceof InventoryView) {
			return ((InventoryView) view);
		}
		return null;
	}

	private class InventorySorter extends ViewerSorter {
		private int columnIndex;
		private final boolean ascending;

		public InventorySorter(int criteria, boolean ascending) {
			super();
			this.columnIndex = criteria;
			this.ascending = ascending;
		}

		@SuppressWarnings("unchecked")
		@Override
		public int compare(Viewer viewer, Object e1, Object e2) {
			int result = 0;
			if (e1 instanceof Ingredient && e2 instanceof Ingredient) {
				result = getComparator().compare(
						labelProvider.getColumnText(e1, columnIndex),
						labelProvider.getColumnText(e2, columnIndex));
			}

			if (!ascending) {
				result = result * -1;
			}
			return result;
		}
	}

}
